namespace DotNetNuke.Services.Exceptions
{
    using DotNetNuke.Common;
    using DotNetNuke.Entities.Modules;
    using DotNetNuke.Entities.Portals;
    using DotNetNuke.Services.Localization;
    using DotNetNuke.Services.Log.EventLog;
    using Microsoft.VisualBasic.CompilerServices;
    using System;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    [StandardModule]
    public sealed class Exceptions
    {
        public static ExceptionInfo GetExceptionInfo(Exception e)
        {
            ExceptionInfo objExceptionInfo = new ExceptionInfo();
            while (e.InnerException != null)
            {
                e = e.InnerException;
            }
            StackFrame sf = new StackTrace(e, true).GetFrame(0);
            try
            {
                MemberInfo mi = sf.GetMethod();
                string res = ((mi.DeclaringType.Namespace + ".") + mi.DeclaringType.Name + ".") + mi.Name;
                objExceptionInfo.Method = res;
            }
            catch (Exception exception1)
            {
                
                Exception ex = exception1;
                objExceptionInfo.Method = "N/A - Reflection Permission required";
                
            }
            if (sf.GetFileName() != "")
            {
                objExceptionInfo.FileName = sf.GetFileName();
                objExceptionInfo.FileColumnNumber = sf.GetFileColumnNumber();
                objExceptionInfo.FileLineNumber = sf.GetFileLineNumber();
            }
            return objExceptionInfo;
        }

        public static void LogException(ModuleLoadException exc)
        {
            new ExceptionLogController().AddLog(exc, ExceptionLogController.ExceptionLogType.MODULE_LOAD_EXCEPTION);
        }

        public static void LogException(PageLoadException exc)
        {
            new ExceptionLogController().AddLog(exc, ExceptionLogController.ExceptionLogType.PAGE_LOAD_EXCEPTION);
        }

        public static void LogException(SchedulerException exc)
        {
            new ExceptionLogController().AddLog(exc, ExceptionLogController.ExceptionLogType.SCHEDULER_EXCEPTION);
        }

        public static void LogException(Exception exc)
        {
            new ExceptionLogController().AddLog(exc, ExceptionLogController.ExceptionLogType.GENERAL_EXCEPTION);
        }

        public static void ProcessModuleLoadException(PortalModuleBase ctrlModule, Exception exc)
        {
            ProcessModuleLoadException(string.Format(DotNetNuke.Services.Localization.Localization.GetString("ModuleUnavailable"), ctrlModule.ModuleConfiguration.ModuleTitle), ctrlModule, exc, true);
        }

        public static void ProcessModuleLoadException(Control UserCtrl, Exception exc)
        {
            ProcessModuleLoadException(DotNetNuke.Services.Localization.Localization.GetString("ErrorOccurred"), UserCtrl, exc);
        }

        public static void ProcessModuleLoadException(PortalModuleBase ctrlModule, Exception exc, bool DisplayErrorMessage)
        {
            ProcessModuleLoadException(string.Format(DotNetNuke.Services.Localization.Localization.GetString("ModuleUnavailable"), ctrlModule.ModuleConfiguration.ModuleTitle), ctrlModule, exc, DisplayErrorMessage);
        }

        public static void ProcessModuleLoadException(string FriendlyMessage, Control UserCtrl, Exception exc)
        {
            if (!ThreadAbortCheck(exc))
            {
                PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
                try
                {
                    if (Convert.ToString(RuntimeHelpers.GetObjectValue(Globals.HostSettings["UseCustomErrorMessages"])) == "N")
                    {
                        throw new ModuleLoadException(FriendlyMessage, exc);
                    }
                    ModuleLoadException lex = new ModuleLoadException(exc.Message.ToString(), exc);
                    new ExceptionLogController().AddLog((BasePortalException) lex);
                    UserCtrl.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container);
                }
                catch(Exception excp)
                {
                    if (System.Convert.ToString(Common.Globals.HostSettings["UseCustomErrorMessages"]) == "Y")
                    {
                        ProcessPageLoadException(excp);
                    }                    
                }
            }
        }

        public static void ProcessModuleLoadException(Control UserCtrl, Exception exc, bool DisplayErrorMessage)
        {
            ProcessModuleLoadException(DotNetNuke.Services.Localization.Localization.GetString("ErrorOccurred"), UserCtrl, exc, DisplayErrorMessage);
        }

        public static void ProcessModuleLoadException(string FriendlyMessage, PortalModuleBase ctrlModule, Exception exc, bool DisplayErrorMessage)
        {
            if (!ThreadAbortCheck(exc))
            {
                PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
                try
                {
                    if (Convert.ToString(RuntimeHelpers.GetObjectValue(Globals.HostSettings["UseCustomErrorMessages"])) == "N")
                    {
                        throw new ModuleLoadException(FriendlyMessage, exc);
                    }
                    ModuleLoadException lex = new ModuleLoadException(exc.Message.ToString(), exc, ctrlModule.ModuleConfiguration);
                    new ExceptionLogController().AddLog((BasePortalException) lex);
                    if (DisplayErrorMessage)
                    {
                        PlaceHolder ErrorPlaceholder = (PlaceHolder) ctrlModule.Parent.FindControl("MessagePlaceHolder");
                        if (ErrorPlaceholder != null)
                        {
                            ctrlModule.Visible = false;
                            ErrorPlaceholder.Visible = true;
                            ErrorPlaceholder.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container);
                        }
                        else
                        {
                            ctrlModule.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container);
                        }
                    }
                }
                catch (Exception excp)
                {
                    if (System.Convert.ToString(Common.Globals.HostSettings["UseCustomErrorMessages"]) == "Y")
                    {
                        ProcessPageLoadException(excp);
                    }
                }
            }
        }

        public static void ProcessModuleLoadException(string FriendlyMessage, Control ctrlModule, Exception exc, bool DisplayErrorMessage)
        {
            if (!ThreadAbortCheck(exc))
            {
                PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
                try
                {
                    if (Convert.ToString(RuntimeHelpers.GetObjectValue(Globals.HostSettings["UseCustomErrorMessages"])) == "N")
                    {
                        throw new ModuleLoadException(FriendlyMessage, exc);
                    }
                    ModuleLoadException lex = new ModuleLoadException(exc.Message.ToString(), exc);
                    new ExceptionLogController().AddLog((BasePortalException) lex);
                    if (DisplayErrorMessage)
                    {
                        PlaceHolder ErrorPlaceholder = (PlaceHolder) ctrlModule.Parent.FindControl("MessagePlaceHolder");
                        if (ErrorPlaceholder != null)
                        {
                            ctrlModule.Visible = false;
                            ErrorPlaceholder.Visible = true;
                            ErrorPlaceholder.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container);
                        }
                        else
                        {
                            ctrlModule.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container);
                        }
                    }
                }
                catch (Exception excp)
                {
                    if (System.Convert.ToString(Common.Globals.HostSettings["UseCustomErrorMessages"]) == "Y")
                    {
                        ProcessPageLoadException(excp);
                    }
                }
            }
        }

        public static void ProcessPageLoadException(Exception exc)
        {
            PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
            ProcessPageLoadException(exc, Globals.ApplicationURL() + "&def=ErrorMessage");
        }

        public static void ProcessPageLoadException(Exception exc, string URL)
        {
            if (!ThreadAbortCheck(exc))
            {
                PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
                if (Convert.ToString(RuntimeHelpers.GetObjectValue(Globals.HostSettings["UseCustomErrorMessages"])) == "N")
                {
                    throw new PageLoadException(exc.Message, exc);
                }
                PageLoadException lex = new PageLoadException(exc.Message.ToString(), exc);
                new ExceptionLogController().AddLog((BasePortalException) lex);
                if (URL != "")
                {
                    if (URL.IndexOf("error=terminate") != -1)
                    {
                        HttpContext.Current.Response.Clear();
                        HttpContext.Current.Server.Transfer("~/ErrorPage.aspx");
                    }
                    else
                    {
                        HttpContext.Current.Response.Redirect(URL, true);
                    }
                }
            }
        }

        public static void ProcessSchedulerException(Exception exc)
        {
            new ExceptionLogController().AddLog(exc, ExceptionLogController.ExceptionLogType.SCHEDULER_EXCEPTION);
        }

        private static bool ThreadAbortCheck(Exception exc)
        {
            if (exc is ThreadAbortException)
            {
                Thread.ResetAbort();
                return true;
            }
            return false;
        }
    }
}

